/**
 *    Copyright (C) 2009 Victor Smirnov <aist11@gmail.com>
 *
 *    This program is free software; you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation; either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License along
 *    with this program; if not, write to the Free Software Foundation, Inc.,
 *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 *    See LICENSE.exceptions in the root folder of this project for possible
 *    exceptions
 *
 */

#ifndef CUBEFS_CORE_TOOLS_CONFIGURATOR_HPP_
#define CUBEFS_CORE_TOOLS_CONFIGURATOR_HPP_

#include <cubefs/api/types.hpp>
#include <cubefs/api/macro.hpp>

#include <cubefs/api/tools/configurator.hpp>

#include <map>
#include <set>
#include <vector>

namespace cubefs{ namespace tools {



class CUBEFS_API Configurator {
public:

	typedef std::map<String, String>	StringMapType;
	typedef std::set<String> 			PropertyListType;

	Configurator(Configurator *parent = NULL);
	virtual ~Configurator() throw ();

	virtual Configurator* GetParent() const;
	virtual void SetParent(Configurator* parent);

	virtual void AddProperty(StringRef name, StringRef value);
	virtual void RemoveProperty(StringRef name);

	virtual bool IsPropertyDefined(StringRef name) const;
	virtual String GetProperty(StringRef name, bool resolve = true) const;

	virtual const StringMapType& GetThisConfigurationProperties() const;

	virtual PropertyListType* 			GetPropertyList() const;

	static Configurator* Parse(StringRef fileName, Configurator* cfg = NULL);

	cubefs::api::Configuration* GetApiPair() const;
	void SetApiPair(cubefs::api::Configuration* pair);

	static String GetLineSeparator();
	static String GetLibraryExtension();
	static String GetPathSeparator();
	static String GetPathSeparatorChar();

	static Configurator* BuildChain(const char** envp, bool read_config_files = true);
protected:

	static Configurator* BuildRootConfigurator(const char** envp);
	static Configurator* BuildPlatformDefaultsConfigurator();

	class NameTree {
		const String* name_;
		NameTree* parent_;
	public:
		NameTree(const String* name, NameTree* parent = NULL):
			name_(name),
			parent_(parent)
		{}

		bool find(StringRef name) const {
			if (name == *name_)
			{
				return true;
			}
			else if (parent_ != NULL)
			{
				return parent_->find(name);
			}
			else
			{
				return false;
			}
		}
	};

	virtual String resolve_references(StringRef value, NameTree* names) const;
	virtual String get_property(StringRef name, NameTree *names, bool resolve) const;

private:
	Configurator* parent_;
	StringMapType properties_;

	cubefs::api::Configuration* api_pair_;
};

Configurator* GetConfiguration();

class CUBEFS_API StringList {
	std::vector<String> list_;
public:
	StringList(StringRef list, StringRef separators = ",");

	int Size() const;
	StringRef GetItem(Int size) const;
};

class PathList: public StringList {
public:
	PathList(StringRef list, StringRef separator = Configurator::GetPathSeparatorChar()): StringList(list, separator) {};
};

}}

#endif
